home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / plug-ins / imagemap / imap_grid.c < prev    next >
Encoding:
C/C++ Source or Header  |  2003-01-15  |  10.9 KB  |  363 lines

  1. /*
  2.  * This is a plug-in for the GIMP.
  3.  *
  4.  * Generates clickable image maps.
  5.  *
  6.  * Copyright (C) 1998-1999 Maurits Rijk  lpeek.mrijk@consunet.nl
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21.  *
  22.  */
  23.  
  24. #include "config.h"
  25.  
  26. #include <stdlib.h>
  27.  
  28. #include "imap_grid.h"
  29. #include "imap_main.h"
  30. #include "imap_menu.h"
  31. #include "imap_popup.h"
  32. #include "imap_preview.h"
  33. #include "imap_table.h"
  34. #include "imap_toolbar.h"
  35.  
  36. #include "libgimp/stdplugins-intl.h"
  37.  
  38. typedef enum {GRID_HIDDEN, GRID_LINES, GRID_CROSSES} GridType_t;
  39.  
  40. static GdkGC *grid_gc;
  41. static gboolean grid_snap = FALSE;
  42. static gint grid_width = 15;
  43. static gint grid_height = 15;
  44. static gint grid_left = 0;
  45. static gint grid_top = 0;
  46. static GridType_t grid_type = GRID_LINES;
  47.  
  48. static void
  49. grid_settings_ok_cb(gpointer data)
  50. {
  51.    GridDialog_t *param = (GridDialog_t*) data;
  52.    gint new_snap;
  53.  
  54.    new_snap = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(param->snap));
  55.    grid_width = gtk_spin_button_get_value_as_int(
  56.       GTK_SPIN_BUTTON(param->width));
  57.    grid_height = gtk_spin_button_get_value_as_int(
  58.       GTK_SPIN_BUTTON(param->height));
  59.    grid_left = gtk_spin_button_get_value_as_int(
  60.       GTK_SPIN_BUTTON(param->left));
  61.    grid_top = gtk_spin_button_get_value_as_int(
  62.       GTK_SPIN_BUTTON(param->top));
  63.  
  64.    if (grid_snap != new_snap) {
  65.       grid_snap = new_snap;
  66.       main_toolbar_set_grid(grid_snap);
  67.       popup_check_grid(grid_snap);
  68.       menu_check_grid(grid_snap);
  69.    }
  70.    redraw_preview();
  71. }
  72.  
  73. static void
  74. snap_toggled_cb(GtkWidget *widget, gpointer data)
  75. {
  76.    GridDialog_t *param = (GridDialog_t*) data;
  77.    gint sensitive = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
  78.  
  79.    gtk_widget_set_sensitive(param->type_frame, sensitive);
  80.    gtk_widget_set_sensitive(param->granularity_frame, sensitive);
  81.    gtk_widget_set_sensitive(param->offset_frame, sensitive);
  82.    gtk_widget_set_sensitive(param->preview, sensitive);
  83. }
  84.  
  85. static void
  86. type_toggled_cb(GtkWidget *widget, gpointer data)
  87. {
  88.    if (GTK_WIDGET_STATE(widget) & GTK_STATE_SELECTED) {
  89.       grid_type = GPOINTER_TO_INT (data);
  90.       redraw_preview();
  91.    }
  92. }
  93.  
  94. static void
  95. toggle_preview_cb(GtkWidget *widget, GridDialog_t *param)
  96. {
  97.    param->enable_preview = 
  98.       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
  99.    redraw_preview();
  100. }
  101.  
  102. static void
  103. grid_assign_value(GtkWidget *widget, gpointer data, gint *value)
  104. {
  105.    GridDialog_t *dialog = (GridDialog_t*) data;
  106.    if (dialog->enable_preview) {
  107.       *value = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
  108.       redraw_preview();        /* Fix me! */
  109.    }
  110. }
  111.  
  112. static void
  113. width_changed_cb(GtkWidget *widget, gpointer data)
  114. {
  115.    grid_assign_value(widget, data, &grid_width);
  116. }
  117.  
  118. static void
  119. height_changed_cb(GtkWidget *widget, gpointer data)
  120. {
  121.    grid_assign_value(widget, data, &grid_height);
  122. }
  123.  
  124. static void
  125. left_changed_cb(GtkWidget *widget, gpointer data)
  126. {
  127.    grid_assign_value(widget, data, &grid_left);
  128. }
  129.  
  130. static void
  131. top_changed_cb(GtkWidget *widget, gpointer data)
  132. {
  133.    grid_assign_value(widget, data, &grid_top);
  134. }
  135.  
  136. static GridDialog_t*
  137. create_grid_settings_dialog()
  138. {
  139.    GridDialog_t *data = g_new(GridDialog_t, 1);
  140.    DefaultDialog_t *dialog;
  141.    GtkWidget *main_table, *table;
  142.    GtkWidget *frame;
  143.    GtkWidget *hbox;
  144.    GtkWidget *button;
  145.    GSList* group;
  146.    
  147.    data->dialog = dialog = make_default_dialog(_("Grid Settings"));
  148.    default_dialog_set_ok_cb(dialog, grid_settings_ok_cb, (gpointer) data);
  149.    
  150.    main_table = gtk_table_new(4, 2, FALSE);
  151.    gtk_container_set_border_width(GTK_CONTAINER(main_table), 10);
  152.    gtk_table_set_row_spacings(GTK_TABLE(main_table), 10);
  153.    gtk_table_set_col_spacings(GTK_TABLE(main_table), 10);
  154.    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog->dialog)->vbox), 
  155.               main_table, TRUE, TRUE, 10);
  156.    gtk_widget_show(main_table);
  157.    
  158.    data->snap = gtk_check_button_new_with_label(_("Snap-To Grid Enabled"));
  159.    gtk_signal_connect(GTK_OBJECT(data->snap), "toggled", 
  160.               (GtkSignalFunc) snap_toggled_cb, data);
  161.    gtk_table_attach_defaults(GTK_TABLE(main_table), data->snap, 0, 1, 0, 1);
  162.    gtk_widget_show(data->snap);
  163.    
  164.    data->type_frame = frame = gtk_frame_new(_("Grid Visibility and Type"));
  165.    gtk_widget_show(frame);
  166.    gtk_table_attach_defaults(GTK_TABLE(main_table), frame, 0, 2, 1, 2);
  167.    hbox = gtk_hbox_new(FALSE, 1);
  168.    gtk_container_add(GTK_CONTAINER(frame), hbox);
  169.    gtk_widget_show(hbox);
  170.  
  171.    data->hidden = button = gtk_radio_button_new_with_label(NULL, _("Hidden"));
  172.    gtk_signal_connect(GTK_OBJECT(button), "toggled", 
  173.               (GtkSignalFunc) type_toggled_cb, GINT_TO_POINTER (GRID_HIDDEN));
  174.    gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 10);
  175.    gtk_widget_show(button);
  176.  
  177.    group = gtk_radio_button_group(GTK_RADIO_BUTTON(button));
  178.    data->lines = button = gtk_radio_button_new_with_label(group, _("Lines"));
  179.    gtk_signal_connect(GTK_OBJECT(button), "toggled", 
  180.               (GtkSignalFunc) type_toggled_cb, (gpointer) GRID_LINES);
  181.    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
  182.    gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 10);
  183.    gtk_widget_show(button);
  184.  
  185.    group = gtk_radio_button_group(GTK_RADIO_BUTTON(button));
  186.    data->crosses = button = gtk_radio_button_new_with_label(group, 
  187.                                 _("Crosses"));
  188.    gtk_signal_connect(GTK_OBJECT(button), "toggled", 
  189.               (GtkSignalFunc) type_toggled_cb, 
  190.               (gpointer) GRID_CROSSES);
  191.    gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 10);
  192.    gtk_widget_show(button);
  193.    
  194.    data->granularity_frame = frame = gtk_frame_new(_("Grid Granularity"));
  195.    gtk_table_attach_defaults(GTK_TABLE(main_table), frame, 0, 1, 2, 3);
  196.    table = gtk_table_new(2, 3, FALSE);
  197.    gtk_container_set_border_width(GTK_CONTAINER(table), 10);
  198.    gtk_table_set_row_spacings(GTK_TABLE(table), 10);
  199.    gtk_table_set_col_spacings(GTK_TABLE(table), 10);
  200.    gtk_container_add(GTK_CONTAINER(frame), table);
  201.  
  202.    create_label_in_table(table, 0, 0, _("Width"));
  203.    data->width = create_spin_button_in_table(table, 0, 1, 15, 1, 100);
  204.    gtk_signal_connect(GTK_OBJECT(data->width), "changed", 
  205.               (GtkSignalFunc) width_changed_cb, (gpointer) data);
  206.    create_label_in_table(table, 0, 2, _("pixels"));
  207.  
  208.    create_label_in_table(table, 1, 0, _("Height"));
  209.    data->height = create_spin_button_in_table(table, 1, 1, 15, 1, 100);
  210.    gtk_signal_connect(GTK_OBJECT(data->height), "changed", 
  211.               (GtkSignalFunc) height_changed_cb, (gpointer) data);
  212.    create_label_in_table(table, 1, 2, _("pixels"));
  213.  
  214.    gtk_widget_show(table);
  215.    gtk_widget_show(frame);
  216.    
  217.    data->offset_frame = frame = gtk_frame_new(_("Grid Offset"));
  218.    gtk_table_attach_defaults(GTK_TABLE(main_table), frame, 1, 2, 2, 3);
  219.    table = gtk_table_new(2, 2, FALSE);
  220.    gtk_container_set_border_width(GTK_CONTAINER(table), 10);
  221.    gtk_table_set_row_spacings(GTK_TABLE(table), 10);
  222.    gtk_table_set_col_spacings(GTK_TABLE(table), 10);
  223.    gtk_container_add(GTK_CONTAINER(frame), table);
  224.  
  225.    data->left = create_spin_button_in_table(table, 0, 0, 0, 0, 100);
  226.    gtk_signal_connect(GTK_OBJECT(data->left), "changed", 
  227.               (GtkSignalFunc) left_changed_cb, (gpointer) data);
  228.    create_label_in_table(table, 0, 1, _("pixels from left"));
  229.  
  230.    data->top = create_spin_button_in_table(table, 1, 0, 0, 0, 100);
  231.    gtk_signal_connect(GTK_OBJECT(data->top), "changed", 
  232.               (GtkSignalFunc) top_changed_cb, (gpointer) data);
  233.    create_label_in_table(table, 1, 1, _("pixels from top"));
  234.  
  235.    data->preview = create_check_button_in_table(main_table, 3, 0, 
  236.                         _("Preview"));
  237.    gtk_signal_connect(GTK_OBJECT(data->preview), "toggled", 
  238.               (GtkSignalFunc) toggle_preview_cb, (gpointer) data);
  239.    gtk_widget_show(data->preview);
  240.  
  241.    snap_toggled_cb(data->snap, data);
  242.  
  243.    gtk_widget_show(table);
  244.    gtk_widget_show(frame);
  245.  
  246.    return data;
  247. }
  248.  
  249. void
  250. do_grid_settings_dialog(void)
  251. {
  252.    static GridDialog_t* dialog;
  253.    GtkWidget *type;
  254.  
  255.    if (!dialog)
  256.       dialog = create_grid_settings_dialog();
  257.  
  258.    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->snap), grid_snap);
  259.    gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->width), grid_width);
  260.    gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->height), grid_height);
  261.    gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->left), grid_left);
  262.    gtk_spin_button_set_value(GTK_SPIN_BUTTON(dialog->top), grid_top);
  263.  
  264.    if (grid_type == GRID_HIDDEN)
  265.       type = dialog->hidden;
  266.    else if (grid_type == GRID_LINES)
  267.       type = dialog->lines;
  268.    else
  269.       type = dialog->crosses;
  270.    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(type), TRUE);
  271.  
  272.    default_dialog_show(dialog->dialog);
  273. }
  274.  
  275. static void
  276. draw_lines(GdkWindow *window, GdkGC* gc, gint width, gint height)
  277. {
  278.    gint x, y;
  279.  
  280.    for (x = grid_left; x < width; x += grid_width)
  281.       draw_line(window, grid_gc, x, 1, x, height);
  282.    for (y = grid_top; y < height; y += grid_height)
  283.       draw_line(window, grid_gc, 1, y, width, y);
  284. }
  285.  
  286. static void
  287. draw_crosses(GdkWindow *window, GdkGC* gc, gint width, gint height)
  288. {
  289.    gint x, y;
  290.  
  291.    for (x = grid_left; x < width; x += grid_width) {
  292.       for (y = grid_top; y < height; y += grid_height) {
  293.      draw_line(window, gc, x - 3, y, x + 3, y);
  294.      draw_line(window, gc, x, y - 3, x, y + 3);     
  295.       }
  296.    }
  297. }
  298.  
  299. void
  300. draw_grid(GtkWidget *preview)
  301. {
  302.    if (grid_snap && grid_type != GRID_HIDDEN) {
  303.       gint width = preview_get_width(preview);
  304.       gint height = preview_get_height(preview);
  305.       
  306.       if (!grid_gc) {
  307.      grid_gc = gdk_gc_new(preview->window);
  308.      gdk_gc_set_line_attributes(grid_gc, 1, GDK_LINE_ON_OFF_DASH,
  309.                     GDK_CAP_BUTT, GDK_JOIN_BEVEL);
  310.       }
  311.       if (grid_type == GRID_LINES)
  312.      draw_lines(preview->window, grid_gc, width, height);
  313.       else
  314.      draw_crosses(preview->window, preview->style->black_gc, width, 
  315.               height);
  316.    }
  317. }
  318.  
  319. gboolean
  320. toggle_grid(void)
  321. {
  322.    grid_snap = !grid_snap;
  323.    redraw_preview();
  324.    return grid_snap;
  325. }
  326.  
  327. static gint
  328. grid_nearest_x(gint x)
  329. {
  330.    return grid_left + (x - grid_left + grid_width / 2) / grid_width 
  331.       * grid_width;
  332. }
  333.  
  334. static gint
  335. grid_nearest_y(gint y)
  336. {
  337.    return grid_top + (y - grid_top + grid_height / 2) / grid_height 
  338.       * grid_height;
  339. }
  340.  
  341. void 
  342. round_to_grid(gint *x, gint *y)
  343. {
  344.    if (grid_snap) {
  345.       *x = grid_nearest_x(*x);
  346.       *y = grid_nearest_y(*y);
  347.    }
  348. }
  349.  
  350. gboolean
  351. grid_near_x(gint x)
  352. {
  353.    return grid_snap && grid_type != GRID_HIDDEN 
  354.       && abs(grid_nearest_x(x) - x) <= 1;
  355. }
  356.  
  357. gboolean
  358. grid_near_y(gint y)
  359. {
  360.    return grid_snap && grid_type != GRID_HIDDEN 
  361.       && abs(grid_nearest_x(y) - y) <= 1;
  362. }
  363.